package fr.enseirb.mycub.activity.component;

import java.util.ArrayList;
import java.util.List;

import android.content.Intent;
import android.database.Cursor;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;

import fr.enseirb.mycub.PrefManager;
import fr.enseirb.mycub.R;
import fr.enseirb.mycub.activity.AbstractPreferencesActivity;
import fr.enseirb.mycub.activity.MainActivity;
import fr.enseirb.mycub.activity.component.layer.Layer;
import fr.enseirb.mycub.db.BikeDBConstants;
import fr.enseirb.mycub.service.UpdateService;

public class MapOverlayComponent {

	public static String ACTION_DETAIL = "fr.inertness.bike.action.VIEW_STATION";
	public static String SHOWING_BALLOON = "showing_balloon";

	private  MapController mapController;

	private  List<Overlay> mapOverlays;

	private  boolean meedZoom = true;
	private  MapView mapView = null;

	GeoPoint bordeaux = new GeoPoint((int)(44.8373682*1E6), (int)(-0.576144*1E6));

	private ArrayList<Layer> mLayers = new ArrayList<Layer>();

	private  boolean forceTask = false;
	private  boolean isFirstFix = true;

	private  int showingBalloon = -1;

	MyLocationComponent myLocationComponent;
	private LocationServiceComponent locationServiceComponent;

	private  boolean satelliteOn = false;
	private  MainActivity activity;

	public MapOverlayComponent(MainActivity activity, Bundle savedInstanceState){
		this.activity = activity;
		mapView = (MapView) activity.findViewById(R.id.map_view);
		mapController = mapView.getController();
		mapOverlays = mapView.getOverlays();

		if(satelliteOn)mapView.setSatellite(true);
		else mapView.setSatellite(false);

		myLocationComponent = new MyLocationComponent(activity, mapView, mapOverlays);
		handleBundle(savedInstanceState);

	}

	public  void onPause(){
		if (getLocationServiceComponent().isBound()) {
			getLocationServiceComponent().onPause();
		}

		//On cache les balloonOverlay
		for(int i = 0; ((i < mLayers.size())); i++){
			// || (showingBalloon != -1)
			Log.i("onPause", " i : "+i+ " mShowingBalloon " +showingBalloon );
			Layer l = mLayers.get(i);
			showingBalloon = l.mStationsOverlay.isBalloonShowing() ?
					l.mStationsOverlay
					.getLastFocusedIndex()
					: -1;
					l.mStationsOverlay.hideBalloon();
		}
		
		//on vide les updates qui seront remis au resume
		Intent intent = new Intent(activity, UpdateService.class);
		intent.setAction(UpdateService.ACTION_CLEAR_UPDATES);
		activity.startService(intent);
		
	}

	public  void onSaveInstanceState(Bundle outState){
		//Partie � revoir pour remettre les balloonOverlay � la r�ouverture
//		for(int i = 0; ((i < mLayers.size())); i++){
//			if (mLayers.get(i).mStationsOverlay.isBalloonShowing()) {
//				outState.putInt(SHOWING_BALLOON, mLayers.get(i).mStationsOverlay
//						.getLastFocusedIndex());
//			}
//		}
	}

	public  void onNewIntent(Intent intent){
		if (ACTION_DETAIL.equals(activity.getIntent().getAction())
				&& !ACTION_DETAIL.equals(intent.getAction())) {
			forceTask = true;
		}
	}

	public  void onResume(MainActivity activity){
		setLocationServiceComponent(new LocationServiceComponent(activity));
		getLocationServiceComponent().onResume(activity);

		//		addLayer(new BikeLayer(activity, getLocationServiceComponent(), mapView, mapOverlays));

		mapView.setBuiltInZoomControls(true);

		Intent intent = activity.getIntent();
		for(int i = 0; i < mLayers.size(); i++){
			mLayers.get(i).mStationsOverlay.setCurrentLocation(null);
		}
		myLocationComponent.resetPosition();
		if (ACTION_DETAIL.equals(intent.getAction())) {
			setStation(intent.getData());
		} else {
			if (!PrefManager.mgr.getBoolean(
					AbstractPreferencesActivity.LOCATION_PREFERENCE, true)
					|| forceTask) {

				for(int i = 0; i < mLayers.size(); i++)
					mLayers.get(i).executePopulateOverlays();

				forceTask = false;
			}
			if (meedZoom) {
				zoomAndCenter(bordeaux);
				meedZoom = false;
			}
		}
	}

	public  void zoomAndCenterOnMyPosition(){
		if(myLocationComponent.isMyLocationDrawn())zoomAndCenter(myLocationComponent.getMyLocation());
	}

	public  void swapBetweenSateliteAndMapView(){
		if(satelliteOn){
			satelliteOn = false;
			mapView.setSatellite(false);
		}
		else{
			satelliteOn = true;
			mapView.setSatellite(true);
		}
	}

	private  void zoomAndCenter(Location location) {
		if (location == null) {
			zoomAndCenter((GeoPoint) null);
			return;
		}
		zoomAndCenter(new GeoPoint((int) (location.getLatitude() * 1E6),
				(int) (location.getLongitude() * 1E6)));
	}

	private  void zoomAndCenter(GeoPoint geoPoint) {
		if (geoPoint == null) {
			mapController.setZoom(14);
			mapController.animateTo(bordeaux);
			return;
		}
		mapController.setZoom(16);
		mapController.animateTo(geoPoint);
	}

	private  void setStation(Uri uri) {
		Cursor station = activity.managedQuery(uri, null, null, null, null); // 2.2...
		ArrayList<Cursor> cursorList = new ArrayList<Cursor>();
		cursorList.add(station);
		//CursorLoader l = new CursorLoader(this, uri, null, null, null, null);
		//Cursor station = l.loadInBackground();
		int latitude = station.getInt(station
				.getColumnIndex(BikeDBConstants.KEY_LATITUDE));
		int longitude = station.getInt(station
				.getColumnIndex(BikeDBConstants.KEY_LONGITUDE));
		for(int i = 0; i < mLayers.size(); i++)
			mLayers.get(i).mStationsOverlay.setItems(
					mLayers.get(i).mStationsOverlay.getOverlaysFromCursor(
							cursorList, getLocationServiceComponent().isBound() ?
									getLocationServiceComponent().getMyLocation() : null, 0));
		zoomAndCenter(new GeoPoint(latitude, longitude));
		mapView.invalidate();
	}


	public void handleBundle(Bundle savedInstanceState){

		if (savedInstanceState != null
				&& savedInstanceState.containsKey(SHOWING_BALLOON)) {
			showingBalloon = savedInstanceState.getInt(SHOWING_BALLOON);
		}

		if (savedInstanceState != null)
			meedZoom = false;
	}

	public  void onLocationChanged(MainActivity activity, Location location, boolean firstFix){
		//		if(location != null) mMyLocationOverlay.setCurrentLocation(location);
		Log.i("MapOverlayComponent", "ON LOCATION CHANGED : "+location);
		myLocationComponent.onLocationChanged(location);

		for(int i = 0; i < mLayers.size(); i++)
			mLayers.get(i).mStationsOverlay.setCurrentLocation(location);

		boolean isDistanceFiltering = PrefManager.mgr.getBoolean(
				AbstractPreferencesActivity.ENABLE_DISTANCE_FILTER, false);
		if ((firstFix || isDistanceFiltering)
				&& !ACTION_DETAIL.equals(activity.getIntent().getAction())) {
			for(int i = 0; i < mLayers.size(); i++)
				mLayers.get(i).executePopulateOverlays();
		} else {
			for(int i = 0; i < mLayers.size(); i++){
				if (mLayers.get(i).mStationsOverlay.isBalloonShowing()) {
					int index = mLayers.get(i).mStationsOverlay.getLastFocusedIndex();
					if (index >= 0 && index < mLayers.get(i).mStationsOverlay.size()) {
						mLayers.get(i).mStationsOverlay.updateBalloonData(mLayers.get(i).mStationsOverlay
								.getItem(index));
					}
				}
			}
			mapView.invalidate();
		}
		if ((isFirstFix && location != null && !MapOverlayComponent.ACTION_DETAIL
				.equals(activity.getIntent().getAction()))
				|| PrefManager.mgr.getBoolean(
						AbstractPreferencesActivity.CENTER_PREFERENCE, false)) {
			zoomAndCenter(location);
		}
		isFirstFix = (location == null) ? true : false;
	}

	public  void onStationsUpdated(MainActivity activity){
		if (ACTION_DETAIL.equals(activity.getIntent().getAction())) {
			setStation(activity.getIntent().getData());
		} else {
			for(int i = 0; i < mLayers.size(); i++)
				mLayers.get(i).executePopulateOverlays();
		}
	}

	public void addLayer(Layer l){
		Log.i("", "l : "+l.getClass().getCanonicalName());
		for(int i = 0; i < mLayers.size(); i++){

			if(mLayers.get(i).getClass().getCanonicalName().equals(l.getClass().getCanonicalName()))
				return;
		}
		mLayers.add(l);
		l.executePopulateOverlays();
	}

	public void removeLayer(Class<? extends Layer> cl){
		Log.e("MapOverlayComponent", "removed : "+cl.getCanonicalName());
		for(int i = 0; i < mLayers.size(); i++){

			if(mLayers.get(i).getClass().getCanonicalName().equals(cl.getCanonicalName())){
				Layer l = mLayers.remove(i);
				l.removeOverlays();
				l.onRemove(activity);
				return;
			}
		}
	}

	public List<Overlay> getMapOverlays() {
		return mapOverlays;
	}

	public void setMapOverlays(List<Overlay> mapOverlays) {
		this.mapOverlays = mapOverlays;
	}

	public MapView getMapView() {
		return mapView;
	}

	public void setMapView(MapView mapView) {
		this.mapView = mapView;
	}

	public int getShowingBalloon() {
		return showingBalloon;
	}

	public void setShowingBalloon(int showingBalloon) {
		this.showingBalloon = showingBalloon;
	}

	public MyLocationComponent getMyLocationComponent() {
		return myLocationComponent;
	}

	public void setMyLocationComponent(MyLocationComponent myLocationComponent) {
		this.myLocationComponent = myLocationComponent;
	}

	public MainActivity getActivity() {
		return activity;
	}

	public void setActivity(MainActivity activity) {
		this.activity = activity;
	}

	public LocationServiceComponent getLocationServiceComponent() {
		return locationServiceComponent;
	}

	public void setLocationServiceComponent(LocationServiceComponent locationServiceComponent) {
		this.locationServiceComponent = locationServiceComponent;
	}

}
